package cn.com.fabric.sdk;

import org.hyperledger.fabric.sdk.*;
import org.hyperledger.fabric.sdk.exception.*;
import org.hyperledger.fabric_ca.sdk.exception.EnrollmentException;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import static cn.com.fabric.sdk.PathConf.*;

/**
 * FabricSDK：在以后使用的时候直接实例化即可
 * @author : sugar without coffee
 * */
public class FabricSDK {

    /**
     * 创建通道
     * */
    public static void createChannel() {
        try {
            UserContext userContext = new UserContext();
            userContext.setAffiliation("Org1");
            userContext.setMspId("Org1MSP");
            userContext.setAccount("李伟");
            userContext.setName("admin");
            Enrollment enrollment =  UserUtils.getEnrollment(org1KeyFolderPath,org1KeyFileName,org1CertFoldePath,org1CertFileName);
            userContext.setEnrollment(enrollment);
            FabricClient fabricClient = new FabricClient(userContext);
            fabricClient.createChannel("test",fabricClient.getOrderer("orderer.example.com","grpcs://orderer.example.com:7050",tlsOrderFilePath),org1TxfilePath);
            Channel channel = fabricClient.getChannel("test");
            channel.addOrderer(fabricClient.getOrderer("orderer.example.com","grpcs://orderer.example.com:7050",tlsOrderFilePath));
            channel.joinPeer(fabricClient.getPeer("peer0.org1.example.com","grpcs://peer0.org1.example.com:7051", org1TlsPeerFilePath));
            channel.initialize();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (CryptoException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        } catch (org.bouncycastle.crypto.CryptoException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (TransactionException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ProposalException e) {
            e.printStackTrace();
        }
    }

    /**
     * invoke 合约
     * invoke(initArgsInvokeRecord,chaincodeName4);
     * @return Object
     * */
    public static boolean invoke(String chainCodeName,String[] initArgs)  {
        try {
            UserContext userContext = new UserContext();
            userContext.setAffiliation("Org1");
            userContext.setMspId("Org1MSP");
            userContext.setAccount("李伟");
            userContext.setName("adminController");
            Enrollment enrollment =  UserUtils.getEnrollment(org1KeyFolderPath, org1KeyFileName, org1CertFoldePath, org1CertFileName);
            userContext.setEnrollment(enrollment);
            FabricClient fabricClient = new FabricClient(userContext);
            Peer peer0 = fabricClient.getPeer("peer0.org1.example.com","grpcs://peer0.org1.example.com:7051", org1TlsPeerFilePath);
            Peer peer1 = fabricClient.getPeer("peer0.org2.example.com","grpcs://peer0.org2.example.com:9051", org2TlsPeerFilePath);
            List<Peer> peers = new ArrayList<>();
            peers.add(peer0);
            peers.add(peer1);
            Orderer order = null;
            order = fabricClient.getOrderer("orderer.example.com","grpcs://orderer.example.com:7050",tlsOrderFilePath);
            fabricClient.invoke("mychannel", TransactionRequest.Type.GO_LANG, chainCodeName, order, peers, "save", initArgs);
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
            return false;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            return false;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return false;
        } catch (InstantiationException e) {
            e.printStackTrace();
            return false;
        } catch (CryptoException e) {
            e.printStackTrace();
            return false;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
            return false;
        } catch (org.bouncycastle.crypto.CryptoException e) {
            e.printStackTrace();
            return false;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return false;
        } catch (ProposalException e) {
            e.printStackTrace();
            return false;
        } catch (TransactionException e) {
            e.printStackTrace();
            return false;
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 查询最新合约
     * String[] initArgsQuery1 = {"10001"};
     * queryAllChaincode(initArgsQuery10003,chaincodeName3)
     * */
    public static Collection queryChaincode(String chainCodeName,String[] initArgs){
        try {
            UserContext userContext = new UserContext();
            userContext.setAffiliation("Org1");
            userContext.setMspId("Org1MSP");
            userContext.setAccount("李伟");
            userContext.setName("adminController");
            Enrollment enrollment = null;
            enrollment = UserUtils.getEnrollment(org1KeyFolderPath, org1KeyFileName, org1CertFoldePath, org1CertFileName);
            userContext.setEnrollment(enrollment);
            FabricClient fabricClient = new FabricClient(userContext);
            Peer peer0 = fabricClient.getPeer("peer0.org1.example.com","grpcs://peer0.org1.example.com:7051", org1TlsPeerFilePath);
            Peer peer1 = fabricClient.getPeer("peer0.org2.example.com","grpcs://peer0.org2.example.com:9051", org2TlsPeerFilePath);
            List<Peer> peers = new ArrayList<>();
            peers.add(peer0);
            peers.add(peer1);
            Map map =  fabricClient.queryChaincode(peers,"mychannel", TransactionRequest.Type.GO_LANG,chainCodeName,"query",initArgs);
            return map.values();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (org.bouncycastle.crypto.CryptoException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (CryptoException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        } catch (ProposalException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (TransactionException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询所有合约
     * queryAllChaincode(initArgsQuery10003,chaincodeName4)
     * @return
     * */
    public static Collection queryAllChaincode(String chainCodeName,String[] initArgs){
        try {
            UserContext userContext = new UserContext();
            userContext.setAffiliation("Org1");
            userContext.setMspId("Org1MSP");
            userContext.setAccount("李伟");
            userContext.setName("adminController");
            Enrollment enrollment = null;
            enrollment = UserUtils.getEnrollment(org1KeyFolderPath, org1KeyFileName, org1CertFoldePath, org1CertFileName);
            userContext.setEnrollment(enrollment);
            FabricClient fabricClient = new FabricClient(userContext);
            Peer peer0 = fabricClient.getPeer("peer0.org1.example.com","grpcs://peer0.org1.example.com:7051", org1TlsPeerFilePath);
            Peer peer1 = fabricClient.getPeer("peer0.org2.example.com","grpcs://peer0.org2.example.com:9051", org2TlsPeerFilePath);
            List<Peer> peers = new ArrayList<>();
            peers.add(peer0);
            peers.add(peer1);
            Map map =  fabricClient.queryChaincode(peers,"mychannel", TransactionRequest.Type.GO_LANG,chainCodeName,"queryHistory",initArgs);
            return map.values();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (org.bouncycastle.crypto.CryptoException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (CryptoException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        } catch (ProposalException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (TransactionException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 安装chaincode
     * */
    public static Object installChaincode(String chaincodeVersion,String chaincodeLocation, String chaincodeName){
        String installOrg1 = SdkInitOrg1.install(chaincodeVersion,chaincodeLocation,chaincodeName).toString();
        String installOrg2 = SdkInitOrg2.install(chaincodeVersion,chaincodeLocation,chaincodeName).toString();
        if("true".equals(installOrg1)&&"true".equals(installOrg2)){
            return "success";
        }else{
            return installOrg1+"\n"+installOrg2;
        }
    }

    /**
     * 合约实例化
     * */
    public static Object instantiated(String chaincodeName,String chaincodeVersion) {
        try{
            UserContext userContext = new UserContext();
            userContext.setAffiliation("Org1");
            userContext.setMspId("Org1MSP");
            userContext.setAccount("李伟");
            userContext.setName("admin");
            Enrollment enrollment =  UserUtils.getEnrollment(org1KeyFolderPath, org1KeyFileName, org1CertFoldePath, org1CertFileName);
            userContext.setEnrollment(enrollment);
            FabricClient fabricClient = new FabricClient(userContext);
            Peer peer = fabricClient.getPeer("peer0.org1.example.com","grpcs://peer0.org1.example.com:7051", org1TlsPeerFilePath);
            Orderer order = fabricClient.getOrderer("orderer.example.com","grpcs://orderer.example.com:7050",tlsOrderFilePath);
            String initArgs[] = {""};
            return fabricClient.initChaincode("mychannel", TransactionRequest.Type.GO_LANG,chaincodeName,chaincodeVersion,order,peer,"init",initArgs);
        }catch (NoSuchMethodException e) {
            return e.toString();
        } catch (NoSuchAlgorithmException e) {
            return e.toString();
        } catch (InstantiationException e) {
            return e.toString();
        } catch (CryptoException e) {
            return e.toString();
        } catch (ClassNotFoundException e) {
            return e.toString();
        } catch (InvalidArgumentException e) {
            return e.toString();
        } catch (InvalidKeySpecException e) {
            return e.toString();
        } catch (org.bouncycastle.crypto.CryptoException e) {
            return e.toString();
        } catch (IllegalAccessException e) {
            return e.toString();
        } catch (ProposalException e) {
            return e.toString();
        } catch (InvocationTargetException e) {
            return e.toString();
        } catch (IOException e) {
            return e.toString();
        } catch (TransactionException e) {
            return e.toString();
        }
    }

    /**
     * 合约升级
     * */
    public static Object upgradeChaincode(String chaincodeName,String chaincodeVersion){
        try{
            UserContext userContext = new UserContext();
            userContext.setAffiliation("Org1");
            userContext.setMspId("Org1MSP");
            userContext.setAccount("李伟");
            userContext.setName("admin");
            Enrollment enrollment =  UserUtils.getEnrollment(org1KeyFolderPath, org1KeyFileName, org1CertFoldePath, org1CertFileName);
            userContext.setEnrollment(enrollment);
            FabricClient fabricClient = new FabricClient(userContext);
            Peer peer = fabricClient.getPeer("peer0.org1.example.com","grpcs://peer0.org1.example.com:7051", org1TlsPeerFilePath);
            Orderer order = fabricClient.getOrderer("orderer.example.com","grpcs://orderer.example.com:7050",tlsOrderFilePath);
            String initArgs[] = {""};
            return fabricClient.upgradeChaincode("mychannel", TransactionRequest.Type.GO_LANG,chaincodeName,chaincodeVersion,order,peer,"init",initArgs);
        }catch (NoSuchMethodException e) {
            e.printStackTrace();
            return e.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return e.toString();
        } catch (InstantiationException e) {
            e.printStackTrace();
            return e.toString();
        } catch (CryptoException e) {
            e.printStackTrace();
            return e.toString();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return e.toString();
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
            return e.toString();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
            return e.toString();
        } catch (org.bouncycastle.crypto.CryptoException e) {
            e.printStackTrace();
            return e.toString();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return e.toString();
        } catch (ProposalException e) {
            e.printStackTrace();
            return e.toString();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            return e.toString();
        } catch (IOException e) {
            e.printStackTrace();
            return e.toString();
        } catch (TransactionException e) {
            e.printStackTrace();
            return e.toString();
        } catch (ChaincodeEndorsementPolicyParseException e) {
            e.printStackTrace();
            return e.toString();
        }
    }


    /**
     * 注册用户 hqCZUStrRTAR
     * UserContext register = new UserContext();
     * register.setName("lihua");
     * register.setAffiliation("org2");
     * */
    public String registerUser(UserContext register) {
       try {
           FabricCAClient caClient = new FabricCAClient("http://192.168.70.43",null);
           Enrollment enrollment = caClient.enroll("admin","adminpw");
           UserContext registar = new UserContext();
           registar.setName("admin");
           registar.setAffiliation("org2");
           registar.setEnrollment(enrollment);
           String secret = caClient.register(registar,register);
           return secret;
       }catch (Exception e){
           e.printStackTrace();
           return e.toString();
       }
    }


    /**
     * 注册用户查询合约
     * String[] initArgs = {"110120"};
     * UserContext userContext = new UserContext();
     * userContext.setAffiliation("Org2");
     * userContext.setMspId("Org2MSP");
     * userContext.setAccount("李伟");
     * userContext.setName("admin");
     * */
    public Collection userQuery(UserContext userContext,String[] initArgs) {
        try{
            FabricCAClient caClient = new FabricCAClient("http://192.168.70.43",null);
            Enrollment enrollment = caClient.enroll("lihua","hqCZUStrRTAR");
            userContext.setEnrollment(enrollment);
            FabricClient fabricClient = new FabricClient(userContext);
            Peer peer0 = fabricClient.getPeer("peer0.org1.example.com","grpcs://peer0.org1.example.com:7051", org1TlsPeerFilePath);
            Peer peer1 = fabricClient.getPeer("peer0.org2.example.com","grpcs://peer0.org2.example.com:9051", org2TlsPeerFilePath);
            List<Peer> peers = new ArrayList<>();
            peers.add(peer0);
            peers.add(peer1);
            Map map =  fabricClient.queryChaincode(peers,"mychannel", TransactionRequest.Type.GO_LANG,"basicinfo","query",initArgs);
            return map.values();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        } catch (org.hyperledger.fabric_ca.sdk.exception.InvalidArgumentException e) {
            e.printStackTrace();
        } catch (CryptoException e) {
            e.printStackTrace();
        } catch (ProposalException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (EnrollmentException e) {
            e.printStackTrace();
        } catch (TransactionException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 注册用户invoke合约
     * String[] initArgs = {"110120", "{\"name\":\"zhangsan\",\"identity\":\"110120\",\"mobile\":\"18910012222\"}"};
     * UserContext userContext = new UserContext();
     * userContext.setAffiliation("Org2");
     * userContext.setMspId("Org2MSP");
     * userContext.setAccount("李伟");
     * userContext.setName("admin");
     * */
    public Object userInvoke(String[] initArgs,UserContext userContext) {
        try{
            FabricCAClient caClient = new FabricCAClient("http://192.168.70.43",null);
            Enrollment enrollment = caClient.enroll("lihua","hqCZUStrRTAR");
            userContext.setEnrollment(enrollment);
            FabricClient fabricClient = new FabricClient(userContext);
            Peer peer0 = fabricClient.getPeer("peer0.org1.example.com","grpcs://peer0.org1.example.com:7051", org1TlsPeerFilePath);
            Peer peer1 = fabricClient.getPeer("peer0.org2.example.com","grpcs://peer0.org2.example.com:9051", org2TlsPeerFilePath);
            List<Peer> peers = new ArrayList<>();
            peers.add(peer0);
            peers.add(peer1);
            Orderer order = fabricClient.getOrderer("orderer.example.com","grpcs://orderer.example.com:7050",tlsOrderFilePath);
            Object result = fabricClient.invoke("mychannel", TransactionRequest.Type.GO_LANG, "basicinfo", order, peers, "save", initArgs);
            return result;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        } catch (org.hyperledger.fabric_ca.sdk.exception.InvalidArgumentException e) {
            e.printStackTrace();
        } catch (CryptoException e) {
            e.printStackTrace();
        } catch (ProposalException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (EnrollmentException e) {
            e.printStackTrace();
        } catch (TransactionException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }
}
